package abc.handler;

import abc.base.IBaseResponse;
import abc.model.ResponseData;
import abc.utils.JacksonUtil;
import abc.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import reactor.netty.ByteBufMono;

@Slf4j
@Component
@Order(-1)
public class FilterExceptionHandler implements ErrorWebExceptionHandler, IBaseResponse {
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        log.error(ex.getMessage(), ex);
        HttpStatus status = HttpStatus.OK;
        if(ex instanceof ResponseStatusException) {
            status = HttpStatus.valueOf(((ResponseStatusException) ex).getStatusCode().value());
        }
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(status);
        String msg = ex.getMessage();
        if(StringUtil.isNotEmpty(msg) && msg.startsWith("ReactiveWebContext resource")) {
            msg = msg.replaceAll("\\[.+\\]", "file");
        }
        ResponseData resultVO = error(msg);  // 自定义的返回对象
        DataBuffer dataBuffer = response.bufferFactory()
                .allocateBuffer(0).write(JacksonUtil.toJson(resultVO).getBytes());
        //基于流形式
        if(!response.isCommitted()) {
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        }
        else {
            return ServerResponse.ok()
                    .contentType(MediaType.APPLICATION_JSON)
                    .bodyValue(dataBuffer)
                    .then();
        }
        return response.writeAndFlushWith(Mono.just(ByteBufMono.just(dataBuffer)));
    }
}
